/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright (c) 2010 by Emiliano Pereyra.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */
package OpenCodes.Persistencia.MySQL.Persona;

import java.sql.Connection;
import java.sql.CallableStatement; //Import para usar procedimientos almacenados
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import OpenCodes.Dominio.Direccion;
import OpenCodes.Dominio.Persona;
import OpenCodes.Persistencia.IMapeadorFila;
import OpenCodes.Persistencia.RepositorioException;
import OpenCodes.Persistencia.UtilidadesDB;

/**
 * 
 * @author emmie
 * 
 */
public class PersonaMySqlRepositorio implements IPersonaRepositorio,
		IMapeadorFila<Persona> {

    private Connection connection;

	public PersonaMySqlRepositorio(Connection connection) {
		this.connection = connection;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ar.com.ergio.demo.persist.IPersonaRepositorio#actualizar(ar.com.ergio
	 * .demo.domain.Persona)
	 */
	@Override
	public void actualizar(Persona persona) throws RepositorioException {
		String sql =
			  " UPDATE persona"
            + "    SET nombre = ?"
			+ "      , apellido = ?"
			+ "      , telefono = ?"
			+ "      , calle = ?"
			+ "      , numero = ?"
			+ "      , piso = ?"
            + "      , departamento = ?"
			+ " WHERE id = ?";

        PreparedStatement preparedStatement = null;
        try {
            // persona
        	preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, persona.getNombre());
            preparedStatement.setString(2, persona.getApellido());
            preparedStatement.setString(3, persona.getTelefono());
            // direccion
            preparedStatement.setString(4, persona.getDireccionParticular().getCalle() == null ? null : persona.getDireccionParticular().getCalle());
            preparedStatement.setInt(5, persona.getDireccionParticular().getNumero());
            preparedStatement.setString(6, persona.getDireccionParticular().getPiso() == null ? null : persona.getDireccionParticular().getPiso());
            preparedStatement.setString(7, persona.getDireccionParticular().getDepartamento() == null ? null : persona.getDireccionParticular().getDepartamento());
            preparedStatement.setInt(8, persona.getId());
            preparedStatement.executeUpdate();

        } catch(SQLException e) {
            throw new RepositorioException("Fallo la actualizacion de la persona " + persona, e);
        } finally {
            UtilidadesDB.close(preparedStatement);
        }
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ar.com.ergio.demo.persist.IPersonaRepositorio#agregar(ar.com.ergio.demo
	 * .domain.Persona)
	 */
	@Override
	public void agregar(Persona persona) throws RepositorioException {
		String sql = 
			  " INSERT INTO persona" 
			+ "    (nombre, apellido, telefono, calle, numero, piso, departamento)"
		    + " VALUES"
		    + "    (?, ?, ?, ?, ?, ?, ?)";
        PreparedStatement preparedStatement = null;
        
        try {
            // persona
            preparedStatement = connection.prepareStatement(sql);
            //preparedStatement.setInt(1, persona.getId());
            preparedStatement.setString(1, persona.getNombre());
            preparedStatement.setString(2, persona.getApellido());
            preparedStatement.setString(3, persona.getTelefono());
            // direccion
            if (persona.getDireccionParticular() != null) {
            	preparedStatement.setString(4, persona.getDireccionParticular().getCalle() == null ? null : persona.getDireccionParticular().getCalle());
                preparedStatement.setInt(5, persona.getDireccionParticular().getNumero());
                preparedStatement.setString(6, persona.getDireccionParticular().getPiso() == null ? null : persona.getDireccionParticular().getPiso());
                preparedStatement.setString(7, persona.getDireccionParticular().getDepartamento() == null ? null : persona.getDireccionParticular().getDepartamento());
            } else {
            	preparedStatement.setString(4, null);
                preparedStatement.setInt(5, 0);
            	preparedStatement.setString(6, null);
                preparedStatement.setString(7, null);
            }
            preparedStatement.executeUpdate();
            
        } catch(SQLException e) {
            throw new RepositorioException("Fallo la insercion de la persona " + persona, e);
        } finally {
            UtilidadesDB.close(preparedStatement);            
        }
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ar.com.ergio.demo.persist.IPersonaRepositorio#cargar(int)
	 */
	@Override
	public Persona cargar(int personaId) throws RepositorioException {
		String sql = 
			  " SELECT id"
			+ "     , nombre"
			+ "     , apellido" 
			+ "     , telefono"
			+ "     , calle"
			+ "     , numero"
			+ "     , piso"
            + "     , departamento"
			+ " FROM persona "
			+ " WHERE id = ?";
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			preparedStatement = connection.prepareStatement(sql);
			preparedStatement.setInt(1, personaId);
			resultSet = preparedStatement.executeQuery();
			if (resultSet.next()) {
				return mapearFila(resultSet);
			}
			return null;
		} catch (SQLException e) {
			throw new RepositorioException("Error en la carga de Persona. ID:" + personaId, e);
		} finally {
			UtilidadesDB.close(resultSet);
			UtilidadesDB.close(preparedStatement);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ar.com.ergio.demo.persist.IPersonaRepositorio#eliminar(ar.com.ergio.demo
	 * .domain.Persona)
	 */
	@Override
	public void eliminar(Persona persona) throws RepositorioException {
		String sql ="delete from persona where id = ?";

		PreparedStatement preparedStatement = null;
        try {
            // Inicia la transacción
            //connection.setAutoCommit(false);

            // elimina la persona
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, persona.getId());
            preparedStatement.executeUpdate();

        } catch(SQLException e) {
            throw new RepositorioException("Fallo la eliminacion de la persona " + persona, e);
        } finally {
            UtilidadesDB.close(preparedStatement);
        }
	}

	@Override
	public List<Persona> listarPersonas() throws RepositorioException {
		String sql = 
			  " SELECT id"
			+ ",nombre"
			+ ",apellido"
			+ ",telefono"
			+ ",calle"
			+ ",numero"
			+ ",piso"
            + ",departamento"
			+ " FROM persona";
		
		List<Persona> lista = new ArrayList<Persona>();
        CallableStatement prcDevolverPersonas = null ;
       	Statement statement = null;
		ResultSet resultSet = null;
		try
        {
            //Obtengo las personas utilizando Procedimientos almacenado
            prcDevolverPersonas = connection.prepareCall("{ call DevolverPersonas() }");
            prcDevolverPersonas.execute();
            resultSet= prcDevolverPersonas.getResultSet();

            //Obtengo las personas utilizando Select Comun
			//statement = connection.createStatement();
			//statement.execute(sql);
			//resultSet = statement.getResultSet();
			while (resultSet.next()) {
				Persona persona = mapearFila(resultSet);
				lista.add(persona);

			}
			return lista;
		} catch (SQLException e) {
			throw new RepositorioException("Falló la carga de la lista", e);
		} finally {
			UtilidadesDB.close(resultSet);
			UtilidadesDB.close(prcDevolverPersonas);
		}
	}

    @Override
    public  List<Persona> buscarPersonas(String nombre, String apellido) throws RepositorioException {
        String sql =
			  " SELECT id"
			+ "     , nombre"
			+ "     , apellido"
			+ "     , telefono"
			+ "     , calle"
			+ "     , numero"
			+ "     , piso"
            + "     , departamento"
			+ " FROM persona "
			+ " WHERE nombre like = ? and apellido like =?";

        List<Persona> lista = new ArrayList<Persona>();
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			preparedStatement = connection.prepareStatement(sql);
			preparedStatement.setString(1, nombre);
            preparedStatement.setString(2, apellido);
			resultSet = preparedStatement.executeQuery();
			while (resultSet.next()) {
				Persona persona = mapearFila(resultSet);
				lista.add(persona);
			}
			return lista;
		} catch (SQLException e) {
			throw new RepositorioException("Error en la busqueda de Nombre: " + nombre + " y Apellido: " + apellido, e);
		} finally {
			UtilidadesDB.close(resultSet);
			UtilidadesDB.close(preparedStatement);
		}
    }

	@Override
	public Persona mapearFila(ResultSet resultSet) throws SQLException {
		int i = 1;
		// persona
		int id = resultSet.getInt(i++);
		String nombre = resultSet.getString(i++);
		String apellido = resultSet.getString(i++);
        String telefono = resultSet.getString(i++);
		// direccion
		String calle = resultSet.getString(i++);
		int numero = resultSet.getInt(i++);
       
        String piso = resultSet.getString(i++);
        String departamento = resultSet.getString(i++);
        // ver campo telefono. Agregar validacion para luego insertarlo en el constructor!

		if (calle != null || numero != 0 || piso !=null || departamento !=null) {
            /**
             * ERROR!!! VERIFICAR CONSTRUCTOR DE LA CLASE DIRECCION!!
             * Direccion direccion = new Direccion(calle,numero,piso,departamento);
             * return new Persona(id, nombre, apellido, telefono, direccion);
             */
			
			
		}
		return new Persona(id, nombre, apellido);
	}

    
}
